<?php
/**
 * Created by PhpStorm.
 * User: sosyuki
 * Date: 2018/3/19
 * Time: 23:25
 */

namespace Drupal\wx_pay;

use Drupal\wx_pay\Entity\WxPayTransaction;
use Exception;

abstract class WxPayController extends EasyWechatApp {

  protected $easyWechat;

  protected $payment;

  public function __construct() {
    $this->easyWechat = $this;
    $this->payment = $this->getPayment();
  }

  abstract static function notifyCallback();

  final function orderUnifyAndBridgeConfig($module, $body, $openid, $total_fee, $device_info, $attach, $trade_type, $json = FALSE) {
    if (variable_get_value('wx_pay_pay_debug')) {
      //如果开启debug 仅支付1分
      $total_fee = 1;
    }
    $wxPay = wx_pay_transaction_load_multiple(FALSE, [
      'module' => $module,
      'openid' => $openid,
      'total_fee' => $total_fee,
      'attach' => $attach,
      'status' => 0,
    ], TRUE);

    if (!empty($wxPay)) {
      $wxPay = reset($wxPay);
      if ($wxPay instanceof WxPayTransaction) {
        if ($wxPay->created + 7000 > REQUEST_TIME && !empty($wxPay->prepay_id)) {
          return $this->bridgeConfig($wxPay->prepay_id, $json);
        }
        $wxPay->delete();
      }
    }
    global $user;
    //生成新单号
    $out_trade_no = $this->makeOutTradeNo();
    $wxPay = new WxPayTransaction();
    $wxPay->uid = $user->uid;
    $wxPay->appid = $this->getAppId();
    $wxPay->mch_id = $this->getMchId();
    $wxPay->module = $module;
    $wxPay->out_trade_no = $out_trade_no;
    $wxPay->openid = $openid;
    $wxPay->total_fee = $total_fee;
    $wxPay->status = 0;
    $wxPay->attach = $attach;
    $wxPay->save();

    $result = $this->orderUnify($body, $total_fee, $out_trade_no, $openid, $trade_type, $device_info, $wxPay->id);
    // var_dump($result);
    $prepayId = $result['prepay_id'];
    if (!empty($prepayId)) {
      $wxPay->prepay_id = $prepayId;
      $wxPay->save();
      return $this->bridgeConfig($prepayId, $json);
    }
    watchdog('支付参数获取失败', serialize($result), [], WATCHDOG_ERROR);
    throw new Exception('支付参数获取失败', 2);
  }

  function bridgeConfig($prepayId, $json) {
    return $this->payment->jssdk->bridgeConfig($prepayId, $json);
  }

  final protected function orderUnify(string $body, int $total_fee, $out_trade_no, $openid, $trade_type, $device_info, $attach = NULL) {
    try {
      $payment = $this->getPayment();
      //统一下单
      $params = [
        'body' => $body,
        'out_trade_no' => $out_trade_no,
        'total_fee' => $total_fee,
        'spbill_create_ip' => ip_address(),
        'trade_type' => $trade_type,
        'openid' => $openid,
        'device_info' => $device_info,
        'attach' => $attach,
      ];
      drupal_alter('wx_pay_order_unify', $params);
      $result = $payment->order->unify($params);
      return $result;
    } catch (Exception $e) {
      watchdog_exception(__FUNCTION__, $e);
      return FALSE;
    }
  }

  protected function _notifyCallback() {
    try {
      $response = $this->payment->handlePaidNotify(function ($message, $fail) {
        // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
        if ($message['return_code'] == 'SUCCESS') {
          // return_code 表示通信状态，不代表支付状态
          // 用户是否支付成功
          if ($message['result_code'] == 'SUCCESS') {
            //调用查询接口 确定支付结果
            $out_trade_no = $message['out_trade_no'];
            $result = $this->payment->order->queryByOutTradeNumber($out_trade_no);
            if ($result['trade_state'] == 'SUCCESS') {
              $wx_paies = wx_pay_transaction_load_multiple(FALSE, [
                'out_trade_no' => $out_trade_no,
                'status' => 0,
              ]);
              if (!empty($wx_paies)) {
                $pay = reset($wx_paies);
                if ($pay instanceof WxPayTransaction) {
                  //写入支付信息
                  $pay->total_fee = $result['total_fee'];
                  $pay->trade_type = $result['trade_type'];
                  $pay->time_end = $result['time_end'];
                  $pay->transaction_id = $result['transaction_id'];
                  $pay->status = 1;
                  $pay->save();

                  module_invoke($pay->module, 'wx_pay_notify', $pay);
                  //hook_wx_pay_common_notify
                  module_invoke_all('wx_pay_common_notify', $pay);
                }
              }
            }
          }
        }
        else {
          return $fail('通信失败，请稍后再通知我');
        }
        return TRUE; // 返回处理完成
      });

      $response->sendContent();
    } catch (Exception $e) {
      watchdog_exception(__FUNCTION__, $e);
    }
  }
}
